home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / cgazv5n4.arc / VIDPRIM.C < prev    next >
C/C++ Source or Header  |  1991-09-23  |  12KB  |  418 lines

  1. /****************************************************************
  2. * File:      VIDPRIM.C
  3. * Date:      Feb. 1991
  4. * Function:  Primitive video operations
  5. * Authors:   Craig Miller, George Spofford
  6. * Compilers:  MSC 6.0, Turbo C++ 1.0, MetaWare HighC-386 1.7
  7. * Switches:
  8. *   MSC 6.0: Assumes large memory model
  9. *     cl -AL -Ox -c vidprim.c
  10. *   High C:
  11. *     hc386 -c -DDOS_386 vidprim.c
  12. *
  13. * Object code may be freely used. Source code may be used freely 
  14. * if authorship/publication is acknowledged
  15. ****************************************************************/
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <stdarg.h>
  21. #include <dos.h> /* for int86(), FP_OFF and FP_SEG macros */
  22. #define VIDPRIM_SRC
  23. #include "vidprim.h"
  24.  
  25. #define N_COLS   80 /* fixed # of columns in std, CGA/EGA/VGA */
  26. #define _TEXTMONO 7 /* code for monochrome text mode */
  27.  
  28. #if ! defined (DOS_386) /* assuming large-model 8086 compile */
  29.  
  30. #define _FAR        far
  31. #define FFMEMCPY    memcpy
  32. #define FF_R_MEMCPY memmove
  33.  
  34. #else /* assuming MetaWare High C-386 v. 1.7 */
  35.  
  36. #define _FAR    _far
  37. #define SS_SEG  0x1C /* Phar Lap's screen segment selector */
  38.  
  39. #define max( a, b) ((a) > (b) ? (a) : (b)) 
  40.  
  41. /* use MetaWare's _movedata function for forward copy */
  42. #define FFMEMCPY( t, f, n) \
  43.   _movedata (FP_SEG(f), FP_OFF(f), FP_SEG(t), FP_OFF(t), n)
  44.  
  45. /* quick define of reverse copy function */
  46. void FF_R_MEMCPY (void _FAR *t, void _FAR *f, int n)
  47. {
  48.   register char _FAR *tp;
  49.   register char _FAR *fp;
  50.   register int loop = n;
  51.  
  52.   for (tp = ((char _FAR *) t) + loop, 
  53.              fp = ((char _FAR *) f) + loop;
  54.         --loop >= 0;
  55.         *--tp = *--fp)
  56.     ;
  57. }
  58.  
  59. #endif
  60.  
  61.                                 /* ptr to display memory */
  62. static short _FAR *dispmem = (short _FAR *) NULL; 
  63.                                 /* current display attribute */
  64. static color_t     curattrib = 0x07;              
  65.                                 /* current display window */
  66. static bbox_t      curbox = {{0,0},{25,80}};      
  67.  
  68. /* Display state: */
  69. static struct {
  70.   int mode; /* mode */
  71.   int cols; /* # of text columns on screen */
  72.   int rows; /* # of text rows on screen */
  73. } CurDispState;
  74.  
  75.  
  76. /* VideoBios1: Makes EGA or VGA video bios call. Used for BIOS 
  77. ** calls that use registers AL - BH as input, and return AL==0x12
  78. ** if successful  (See BIOS #defines in VIDPRIM.H)
  79. */
  80. int VideoBios1 (unsigned char al, unsigned char ah,
  81.                 unsigned char bl, unsigned char bh)
  82. {
  83.   union REGS inregs, outregs;
  84.  
  85.   inregs.h.al = al;
  86.   inregs.h.ah = ah;
  87.   inregs.h.bl = bl;
  88.   inregs.h.bh = bh;
  89.   int86 ( 0x10, &inregs, &outregs);
  90.   return ( outregs.h.al == 0x12 );
  91. }
  92.  
  93.  
  94. /* VideoBios2: Makes EGA or VGA video bios call. Used for BIOS
  95. ** calls that use registers AL - BL as input and BH as output. 
  96. ** Returns register BH. (See BIOS #defines in VIDPRIM.H)
  97. */
  98. unsigned char VideoBios2 (unsigned char al, unsigned char ah,
  99.                           unsigned char bl)
  100. {
  101.   union REGS inregs, outregs;
  102.  
  103.   inregs.h.al = al;
  104.   inregs.h.ah = ah;
  105.   inregs.h.bl = bl;
  106.   int86 ( 0x10, &inregs, &outregs);
  107.   return ( outregs.h.bh );
  108. }
  109.  
  110.  
  111. /* InitDisplay: Sets the text display to the given mode (3 or 7) 
  112. ** and the number of text lines given.
  113. */
  114. void _PASCAL InitDisplay (int mode, int rows)
  115. {
  116.   EGA_setvideomode (mode); /* set the mode (either 3 or 7) */
  117.   CurDispState.mode = mode;
  118.   CurDispState.cols = N_COLS;
  119.  
  120.   switch (rows) {
  121.    case 50:
  122.     VGA_400lines();
  123.     CurDispState.rows = 50;
  124.     EGA_SetFont (FONT8X8NORESET);
  125.     break;
  126.    case 43:
  127.     CurDispState.rows = 43;
  128.     EGA_SetFont (FONT8X8NORESET);
  129.     break;
  130.    case 25:
  131.    default:
  132.     VGA_400lines();
  133.     EGA_SetFont (FONT8X16NORESET);
  134.     CurDispState.rows = 25;
  135.   }
  136.  
  137. #if ! defined (DOS_386)
  138.   dispmem = (short _FAR *)
  139.     ((CurDispState.mode == _TEXTMONO) ? 0xB0000000 : 0xB8000000);
  140. #else
  141.   { /* 48-bit far ptr creation */
  142.     struct _farptrovly {int off; short seg;};
  143.  
  144.     ((struct _farptrovly *) &dispmem)->seg = 
  145.                         SS_SEG; /* Phar Lap screen seg */
  146.     ((struct _farptrovly *) &dispmem)->off = 0x00000000;
  147.   }
  148. #endif
  149.  
  150.   curbox.o[DOWN] = 0;
  151.   curbox.o[ACROSS] = 0;
  152.   curbox.n[DOWN] = CurDispState.rows;
  153.   curbox.n[ACROSS] = CurDispState.cols;
  154.  
  155.   curattrib = 0x07;
  156. }
  157.  
  158.  
  159. /* SetCurAttrib: Sets the current display attribute.  
  160. ** Returns the previous current-attribute value.
  161. */
  162. color_t SetCurAttrib (color_t attr)
  163. {
  164.   color_t ret;
  165.  
  166.   ret = curattrib;
  167.   curattrib = attr;
  168.   return (ret);
  169. }
  170.  
  171.  
  172. /* SetCurBox
  173. ** Sets the current screen display window
  174. */
  175. void SetCurBox (bbox_t *bbp)
  176. {
  177.   memcpy (&curbox, bbp, sizeof (bbox_t));
  178. }
  179.  
  180.  
  181. /* SetTextCursor: Sets current cursor position to 
  182. ** R,C (coordinate system starts at 0, 0)
  183. */
  184. void _PASCAL SetTextCursor (int r, int c)
  185. {
  186.   union REGS regs;
  187.  
  188.   regs.h.ah = 0x02;           /* func. is set cursor position */
  189.   regs.h.bh = 0;
  190.   regs.h.dh = (char) r;
  191.   regs.h.dl = (char) c;
  192.   int86 (0x10, ®s, ®s); /* set cursor at row, col */
  193. }
  194.  
  195.  
  196. /* ScrollBox: Scrolls the given region down by ND rows and 
  197. ** right by NA columns
  198. */
  199. void _PASCAL ScrollBox (bbox_t *bbp, int nd, int na)
  200. {
  201.   short _FAR *tptr;   /* primary display memory ptr */
  202.   short _FAR *fptr;   /* secondary display ptr */
  203.   register int loop;  /* primary loop index */
  204.   register int loop2; /* secondary loop index */
  205.   short _FAR *boxptr; /* ptr to UL corner of scroll-box */
  206.   short attr;         /* background filler */
  207.   int nbytes;         /* # of bytes to transfer per move */
  208.  
  209.   /* calculate region reference ptr */
  210.   boxptr = dispmem + bbp->o[DOWN] * CurDispState.cols 
  211.                    + bbp->o[ACROSS];
  212.   /* make newly-blank-space representation */
  213.   attr = ((short) (curattrib << 8)) + ' ';
  214.  
  215.   /*-------------------   VERTICAL   ------------------------*/
  216.   if (nd != 0) {                 /* if scrolling  vertically */
  217.     nbytes = bbp->n[ACROSS] *       /* scroll the entire     */
  218.                 sizeof(short);      /* width of the box.     */
  219.     if (nd < 0) {
  220.  
  221.       /*----------------------- SCROLL UP -------------------*/
  222.       nd = -nd;
  223.       if (nd > bbp->n[DOWN]) /* clip # to scroll to box size */
  224.         nd = bbp->n[DOWN];
  225.  
  226.       /* copy rows, advancing downwards */
  227.       for (tptr = boxptr, fptr = 
  228.                 boxptr + nd * CurDispState.cols,
  229.         loop = bbp->n[DOWN] - nd;
  230.         --loop >= 0;
  231.         tptr += CurDispState.cols, fptr += CurDispState.cols)
  232.         FFMEMCPY (tptr, fptr, nbytes);
  233.  
  234.       /* blank each remaining row with current attribute
  235.        * tptr is set to first row after scrolled region. */
  236.  
  237.       for (loop2 = nd, fptr = tptr; --loop2 >= 0;
  238.                  fptr += CurDispState.cols)
  239.         for (tptr = fptr, loop = bbp->n[ACROSS]; 
  240.                   --loop >= 0; *tptr++ = attr)
  241.           ;
  242.     }
  243.     else {
  244.       /*------------------- SCROLL DOWN ---------------------*/
  245.       if (nd > bbp->n[DOWN]) /* clip to region */
  246.         nd = bbp->n[DOWN];
  247.  
  248.       /* copy rows, advancing upwards */
  249.       for (tptr = boxptr + (bbp->n[DOWN]-1) * CurDispState.cols,
  250.         fptr = boxptr + (bbp->n[DOWN]-1-nd) * CurDispState.cols,
  251.         loop = bbp->n[DOWN] - nd;
  252.         --loop >= 0;
  253.         tptr -= CurDispState.cols, fptr -= CurDispState.cols)
  254.         FFMEMCPY (tptr, fptr, nbytes);
  255.  
  256.       /* blank each remaining rows with current attribute
  257.        * tptr is set to first row above scrolled region. */
  258.       for (loop2 = nd, fptr = tptr; --loop2 >= 0; 
  259.                 fptr -= CurDispState.cols)
  260.         for (tptr = fptr, loop = bbp->n[ACROSS]; 
  261.                 --loop >= 0; *tptr++ = attr)
  262.           ;
  263.     }
  264.   } /* vertical scroll */
  265.  
  266.   /*---------------    HORIZONTAL    ------------------------*/
  267.   if (na != 0) { /* if any horizontal scroll */
  268.     if (na > 0) {
  269.  
  270.       /*----------------- SCROLL RIGHT ----------------------*/
  271.       /* scroll only NA chars */
  272.       nbytes = (bbp->n[ACROSS] - na) * sizeof (short);
  273.       if (na > bbp->n[ACROSS]) /* clip to size of box */
  274.         na = bbp->n[ACROSS];
  275.  
  276.       /* in each row, slide columns to 
  277.                 screen right (-> high memory) */
  278.       for (fptr = boxptr, tptr = boxptr + na, 
  279.                         loop = bbp->n[DOWN];
  280.         --loop >= 0;
  281.         fptr += CurDispState.cols, tptr += CurDispState.cols)
  282.         /* copy from high- to low-mem */
  283.         FF_R_MEMCPY (tptr, fptr, nbytes); 
  284.  
  285.       /* in each row, blank unmoved columns */
  286.       for (loop2 = bbp->n[DOWN], fptr = boxptr; --loop2 >= 0; 
  287.                 fptr += CurDispState.cols)
  288.         for (tptr = fptr, loop = na; --loop >= 0; *tptr++ = attr)
  289.           ;
  290.     }
  291.     else {
  292.  
  293.       /*----------------- SCROLL LEFT -----------------------*/
  294.       na = -na;                /* take positive quantity */
  295.       nbytes = (bbp->n[ACROSS] - na) * sizeof (short);
  296.       if (na > bbp->n[ACROSS]) /* clip to box */
  297.         na = bbp->n[ACROSS];
  298.  
  299.       /* in each row, move columns to 
  300.                 screen left (-> low memory) */
  301.       for (tptr = boxptr, fptr = boxptr + na, 
  302.                 loop = bbp->n[DOWN];
  303.         --loop >= 0;
  304.         tptr += CurDispState.cols, fptr += CurDispState.cols)
  305.         FFMEMCPY (tptr, fptr, nbytes);
  306.  
  307.       /* blank out unmoved columns */
  308.       for (loop2 = bbp->n[DOWN], fptr = 
  309.                    boxptr + bbp->n[ACROSS] - na;
  310.         --loop2 >= 0;
  311.         fptr += CurDispState.cols)
  312.         for (loop = na, tptr = fptr; --loop >= 0; 
  313.                    *tptr++ = attr)
  314.           ;
  315.     }
  316.   } /* horizontal scroll */
  317. }
  318.  
  319.  
  320. /* ClearBox: Clears out region represented in bounding box 
  321. ** to current attribute.
  322. */
  323. void ClearBox (bbox_t *bbp)
  324. {
  325.   ScrollBox (bbp, bbp->n[DOWN], 0);
  326. }
  327.  
  328.  
  329.  
  330. /* ClearScreen
  331. ** Clears screen to currently set attribute.
  332. */
  333. void ClearScreen (void)
  334. {
  335.   bbox_t bbox;
  336.  
  337.   BBSET( bbox, 0, 0, CurDispState.rows, CurDispState.cols);
  338.   ClearBox (&bbox);
  339. }
  340.  
  341.  
  342. /* CursorOff
  343. ** Turns text cursor off.
  344. */
  345. void CursorOff (void)
  346. {
  347.   SetTextCursor (CurDispState.rows + 1, 0);
  348. }
  349.  
  350.  
  351. /* x_outch: Places a character on the screen, at R,C 
  352. ** using the current text-rendering attributes.  
  353. ** Returns # of chars put of screen (1 or 0)
  354. */
  355. int _PASCAL x_outch (int r, int c, char ch)
  356. {
  357.   register short _FAR *locdispmem;
  358.   /* clip to current box */
  359.   if (   ((unsigned) r) >= ((unsigned) curbox.n[DOWN])
  360.     || ((unsigned) c) >= ((unsigned) curbox.n[ACROSS]) )
  361.     return (0);
  362.  
  363.   locdispmem = dispmem + ((curbox.o[DOWN] + r) * 
  364.                 CurDispState.cols + curbox.o[ACROSS] + c);
  365.   *locdispmem = (short) (curattrib << 8) + (unsigned char) ch;
  366.   return (1);
  367. }
  368.  
  369.  
  370.  
  371. /* x_outtext: Places a character string on the screen 
  372. ** starting at R,C, using the current text-rendering attributes
  373. */
  374. int _PASCAL x_outtext (int r, int c, char *str)
  375. {
  376.   register short _FAR *locdispmem;
  377.   register char       *cp;
  378.   int         n, total;
  379.   short       attrmask;
  380.  
  381.   /* clip to box */
  382.   /* if out of curbox */
  383.   if (   ((unsigned) r) >= ((unsigned) curbox.n[DOWN])
  384.     || ((unsigned) c) >= ((unsigned) curbox.n[ACROSS]) )
  385.     return (0);
  386.  
  387.   locdispmem = dispmem + (curbox.o[DOWN] + r) * 
  388.         CurDispState.cols + curbox.o[ACROSS] + c;
  389.   attrmask = curattrib << 8;
  390.   for (cp = str, n = max (0, curbox.n[ACROSS] - c), total = 0;
  391.     *cp && --n >= 0;
  392.     ++total)
  393.     *locdispmem++ = attrmask | * (unsigned char *) cp++;
  394.  
  395.   return (total);
  396. }
  397.  
  398. /* xput_string
  399. ** Acts as a screen-printf() with row, column addressing
  400. */
  401. int _CDECL xput_string (int r, int c, char *fmt,...)
  402. {
  403.   static char buf[256];
  404.   va_list argptr;
  405.   /* if out of curbox, don't write */
  406.   if (   ((unsigned) r) >= ((unsigned) curbox.n[DOWN])
  407.     || ((unsigned) c) >= ((unsigned) curbox.n[ACROSS]) )
  408.     return (0);
  409.  
  410.   va_start (argptr, fmt); /* format arguments */
  411.   vsprintf (buf, fmt, argptr);
  412.   va_end (argptr);
  413.  
  414.   return (x_outtext (r, c, buf));
  415. }
  416.  
  417. /* END OF VIDPRIM.C */
  418.